﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Core.Model;
using DapperExtensions;
using DapperExtensions.Mapper;
using log4net;

namespace DataServer.Dao
{
    public class DeviceCategoryDao : BaseDao<DeviceCategory>
    {
        private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static ChannelMapper _channelMapper;

        public DeviceCategoryDao()
        {
            if (_channelMapper == null)
            {
                _channelMapper = new ChannelMapper();
            }
        }

        protected override string GetTableName()
        {
            if (_channelMapper != null)
                return _channelMapper.TableName;
            return "channel";
        }

        public override List<DeviceCategory> GetEntities()
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                // 并行模式下会报错 There is already an open DataReader associated with this Command which must be closed first
                // 原因是Dapper 中的协程
                IList<ISort> sort = new List<ISort>();
                sort.Add(new Sort { PropertyName = "Position", Ascending = true });
                return result?.Connection.GetAll<DeviceCategory>(sort).ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public List<DeviceCategory> GetCatgoryWithDevices()
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                IList<ISort> sort = new List<ISort>();
                sort.Add(new Sort { PropertyName = "Position", Ascending = true });
                var list = result?.Connection.GetAll<DeviceCategory>(sort).ToList();
                if(list==null || list.Count == 0)
                {
                    return null;
                }
                for(int i=0;i< list.Count;i++)
                {
                    if (string.IsNullOrEmpty(list[i].Devices)) continue;
                    // select * From 表 Where id in (1,5,3) order by instr(',1,5,3,',',CONCAT(',',id,',')) // 按IN 语句排序
                    string sql = $"select * From device Where Id in ({ list[i].Devices}) order by instr(',{list[i].Devices},', concat(',', Id, ','))";
                    //string sql = $"SELECT * FROM device WHERE Id IN({list[i].Devices})";
                    IEnumerable<Device> devices = result?.Connection.GetList<Device>(sql);
                    if(devices != null && devices.Count() > 0)
                    {
                        list[i].DeviceDict = new Dictionary<string, Device>();
                        foreach(var dev in devices)
                        {
                            list[i].DeviceDict.Add(dev.Id, dev);
                        }
                    }
                }
                return list;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public DeviceCategory GetEntityById(string id)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<DeviceCategory>(f => f.Id, Operator.Eq, id);
                DeviceCategory category = result?.Connection.Get<DeviceCategory>(predicate);
                return category;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public DeviceCategory GetEntityByName(string name)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<DeviceCategory>(f => f.Name, Operator.Eq, name);
                DeviceCategory channel = result?.Connection.Get<DeviceCategory>(predicate);
                return channel;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

    }
    public sealed class DeviceCategoryMapper : ClassMapper<DeviceCategory>
    {
        public DeviceCategoryMapper()
        {
            Table("device_category");
            Map(x => x.Id).Key(KeyType.Assigned);
            Map(x => x.DeviceDict).Ignore();
            Map(x => x.IsEditing).Ignore();
            //Ignore this property entirely
            //optional, map all other columns
            AutoMap();
        }
    }
}
